#pragma once
#include <cmath>
#include <limits>

//================================================================================================================================
// Отключение стандартного механизма копирования объектов класса.
//
// На основе Google Code Style.
//
// Встроенный механизм копирования может вызываться в программе неявно, снижая производительность. Поскольку неявные вызовы
// очень сложно обнаружить при отладке программы, везде, где это возможно, предпочтительной является замена конструктора и
// оператора копирования копирующим методом класса. Для отключения встроенного механизма копирования необходимо определить
// оператор и конструктор копирования в закрытой (private) области класса. Данный макрос делает определение этих функций в
// закрытой области класса более понятным для тех, кто будет читать код.
//================================================================================================================================
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&);             \
    TypeName& operator=(const TypeName&)

//================================================================================================================================
// Функции сравнения вещественных чисел.
//
// На основе материалов из книги The Art of Computer Programming (автор Дональд Кнут).
//
// В качестве малой величины epsilon взято значение 16*DBL_EPSILON, где DBL_EPSILON (минимальное число, которое при сложении
// с единицей дает число отличное от единицы) определено в стандартной библиотеке C++. Согласно различным источникам в интернете
// это позволяет при сравнении не учитывать последние несколько бит мантиссы (примерно 1.5 значащие цифры в десятичном
// представлении), что полезно, т.к. на практике погрешность вычислений часто может приводить к разнице в более чем один бит в
// двоичном представлении чисел.
//================================================================================================================================
inline bool approximatelyEqual(double a, double b)
{
    return std::fabs(a - b) <= 16*std::max(std::fabs(a), std::fabs(b))*std::numeric_limits<double>::epsilon();
}

inline bool essentiallyEqual(double a, double b)
{
    return std::fabs(a - b) <= 16*std::min(std::fabs(a), std::fabs(b))*std::numeric_limits<double>::epsilon();
}

inline bool definitelyGreaterThan(double a, double b)
{
    return a - b > 16*std::max(std::fabs(a), std::fabs(b))*std::numeric_limits<double>::epsilon();
}

inline bool definitelyLessThan(double a, double b)
{
    return b - a > 16*std::max(std::fabs(a), std::fabs(b))*std::numeric_limits<double>::epsilon();
}